<!--
 * @Author: 张鹏
 * @Date: 2025-01-27 10:00:00
 * @LastEditors: fyukeeh 15849141465@163.com
 * @LastEditTime: 2025-08-01 09:10:02
 * @FilePath: \mapbox\src\views\example\Buildings3D.vue
 * @Description: 3D建筑显示demo - 使用MapTiler + fill-extrusion
-->
<template>
  <div class="map-page">
    <div id="map" class="map-container"></div>
    <div class="info-panel">
      <h3>3D建筑显示</h3>
      <p>使用MapTiler矢量瓦片 + fill-extrusion图层</p>
      <div class="controls">
        <el-button @click="toggleBuildings" :type="buildingsVisible ? 'primary' : 'default'">
          {{ buildingsVisible ? '隐藏建筑' : '显示建筑' }}
        </el-button>
        <el-button @click="resetView">重置视角</el-button>
      </div>
      <div class="info">
        <p><strong>当前缩放等级：</strong>{{ zoomLevel }}</p>
        <p><strong>建筑高度范围：</strong>{{ heightRange }}</p>
        <p><strong>建筑数量：</strong>{{ buildingCount }}</p>
      </div>
    </div>
  </div>
</template>

<script setup>
import { onMounted, ref, onUnmounted } from 'vue'
import Map from '289-map'

// MapTiler API Key (请替换为您自己的key)
const MAPTILER_KEY = 'qC0veBxoTx1YwVioOuvc'

const buildingsVisible = ref(true)
const zoomLevel = ref(15)
const heightRange = ref('0-200m')
const buildingCount = ref(0)

let map
let buildingLayerId = '3d-buildings'

onMounted(() => {
  // 初始化地图
  map = new Map('map', {
    style: `https://api.maptiler.com/maps/basic-v2/style.json?key=${MAPTILER_KEY}`,
    scene: {
      center: { lng: 116.397, lat: 39.916 }, // 北京天安门
      zoom: 15.5,
      pitch: 45,
      bearing: -17.6
    },
    controller: ['globe', 'showZoom', 'showCompass', 'visualizePitch'],
    type: 'mercator',
  })

  // 地图加载完成后添加3D建筑图层
  map.on('load', () => {
    add3DBuildings()
    updateInfo()
  })

  // 监听缩放事件
  map.on('zoom', () => {
    zoomLevel.value = Math.round(map.getZoom() * 10) / 10
    updateInfo()
  })

  // 监听地图移动事件
  map.on('move', () => {
    updateInfo()
  })
})

onUnmounted(() => {
  if (map) {
    map.destroy()
  }
})

// 添加3D建筑图层
function add3DBuildings() {
  const mapInstance = map.getMapInstance()
  
  // 获取标签图层ID，用于在标签下方插入建筑图层
  const layers = mapInstance.getStyle().layers
  let labelLayerId
  for (let i = 0; i < layers.length; i++) {
    if (layers[i].type === 'symbol' && layers[i].layout['text-field']) {
      labelLayerId = layers[i].id
      break
    }
  }

  // 添加MapTiler矢量瓦片源
  if (!mapInstance.getSource('openmaptiles')) {
    mapInstance.addSource('openmaptiles', {
      url: `https://api.maptiler.com/tiles/v3/tiles.json?key=${MAPTILER_KEY}`,
      type: 'vector',
    })
  }

  // 添加3D建筑图层
  if (!mapInstance.getLayer(buildingLayerId)) {
    mapInstance.addLayer({
      'id': buildingLayerId,
      'source': 'openmaptiles',
      'source-layer': 'building',
      'type': 'fill-extrusion',
      'minzoom': 15,
      'filter': ['!=', ['get', 'hide_3d'], true],
      'paint': {
        // 建筑颜色：根据高度渐变
        'fill-extrusion-color': [
          'interpolate',
          ['linear'],
          ['get', 'render_height'],
          0, '#f0f0f0',
          50, '#d0d0d0', 
          100, '#a0a0a0',
          150, '#707070',
          200, '#404040'
        ],
        // 建筑高度：根据缩放级别动态调整
        'fill-extrusion-height': [
          'interpolate',
          ['linear'],
          ['zoom'],
          15, 0,
          16, ['get', 'render_height']
        ],
        // 建筑基础高度
        'fill-extrusion-base': [
          'interpolate',
          ['linear'],
          ['zoom'],
          15, 0,
          16, ['get', 'render_min_height']
        ],
        // 建筑透明度
        'fill-extrusion-opacity': 0.8
      }
    }, labelLayerId)
  }
}

// 切换建筑显示/隐藏
function toggleBuildings() {
  const mapInstance = map.getMapInstance()
  const layer = mapInstance.getLayer(buildingLayerId)
  
  if (layer) {
    const visibility = buildingsVisible.value ? 'none' : 'visible'
    mapInstance.setLayoutProperty(buildingLayerId, 'visibility', visibility)
    buildingsVisible.value = !buildingsVisible.value
  }
}

// 重置视角
function resetView() {
  map.flyTo({
    center: { lng: 116.397, lat: 39.916 },
    zoom: 15.5,
    pitch: 45,
    bearing: -17.6,
    duration: 2000
  })
}

// 更新信息面板
function updateInfo() {
  if (!map) return
  
  const mapInstance = map.getMapInstance()
  const zoom = map.getZoom()
  
  // 根据缩放级别更新高度范围
  if (zoom < 16) {
    heightRange.value = '2D模式'
  } else {
    heightRange.value = '0-200m'
  }
  
  // 获取当前视野内的建筑数量（简化计算）
  const bounds = map.getBounds()
  const area = (bounds.getEast() - bounds.getWest()) * (bounds.getNorth() - bounds.getSouth())
  buildingCount.value = Math.round(area * 1000) // 简化估算
}
</script>

<style scoped>
.map-page {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.map-container {
  width: 100%;
  height: 100%;
}

.info-panel {
  position: absolute;
  top: 20px;
  left: 20px;
  background: rgba(255, 255, 255, 0.95);
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  max-width: 300px;
  z-index: 1000;
}

.info-panel h3 {
  margin: 0 0 10px 0;
  color: #333;
  font-size: 18px;
}

.info-panel p {
  margin: 5px 0;
  color: #666;
  font-size: 14px;
}

.controls {
  margin: 15px 0;
}

.controls .el-button {
  margin-right: 10px;
  margin-bottom: 10px;
}

.info {
  margin-top: 15px;
  padding-top: 15px;
  border-top: 1px solid #eee;
}

.info p {
  margin: 5px 0;
  font-size: 13px;
}

.info strong {
  color: #333;
}
</style> 